(function() {

    var $u = juliet.using({ validator : 'juliet.validation.validator' });

    var validatorMetadataUpdaterObject = {

        plugins : { },

        eachValidator : function(chains, callback) {
            var chainUid;

            for (chainUid in chains) {
                var chain = chains[chainUid], validatorUid;

                for (validatorUid in chain.validators) {
                    callback({ chain : chain, validatorUid : validatorUid });
                }
            }
        },

        run : function(chains) {
            for (var pluginName in this.plugins) this.plugins[pluginName].run(chains);
        }

    };

    validatorMetadataUpdaterObject.plugins.verify = {

        updateOptions : function(validators) {
            if (validators.length != 2) return;

            var first = validators[0], second = validators[1];

            first.metadata.verifyValidator = second;
            second.metadata.verifyValidator = first;
        },

        run : function(chains) {
            var
            groupHash = { },
            Verify = $u('validator').Verify;

            validatorMetadataUpdaterObject.eachValidator(chains, function(o) {
                var validator = o.chain.validators[o.validatorUid];

                if (!(validator instanceof Verify)) return;

                var validationGroup = validator.metadata.options.group;

                groupHash[validationGroup] = groupHash[validationGroup] || [];
                groupHash[validationGroup].push(validator);
            });

            for (var groupName in groupHash) this.updateOptions(groupHash[groupName]);
        }

    };

    validatorMetadataUpdaterObject.plugins.custom = {

        run : function(chains) {
            var Custom = $u('validator').Custom;

            validatorMetadataUpdaterObject.eachValidator(chains, function(o) {
                var validator = o.chain.validators[o.validatorUid];

                if (!(validator instanceof Custom)) return;

                validator.metadata.options.continueValidation = function(result) {
                    o.chain.validate({
                        currentValidator : validator,
                        validationResult : result,
                        continueValidation : true,
                        validationEvent : validator.validationEvent
                    });
                };
            });
        }

    };

    juliet.registerModule('juliet.validation', 'validatorMetadataUpdater', validatorMetadataUpdaterObject);

})();
